﻿using _80X_CG_Frame.Interfaces;
using _80X_CG_Frame.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace _80X_CG_Frame.Objects
{
    /// <summary>
    /// 扫码枪
    /// </summary>
    public class 扫码枪 : AsyncClient, I扫码枪
    {

        static int max_fail = 5;//超x次失败重连
        int fail_count;
        int maxBufferSize = 1024;
        static string barcode_pattern = "~(?<barcode>.*?)\r\n";//条码正则
        static Regex barcode_regex = new Regex(barcode_pattern, RegexOptions.IgnoreCase);

        public 扫码枪()
        {
            fail_count = 0;
        }

        private bool Read(ref string result)
        {
            byte[] byteReceive = new byte[maxBufferSize];

            lock (client)
            {
                try
                {
                    if (ns != null && IsConnect)
                    {

                        if (ns.CanRead)
                        {
                            int len = ns.Read(byteReceive, 0, maxBufferSize);

                            if (len > 0)
                            {
                                //result = ByteArrayToStr(byteReceive, len);
                                result = Encoding.ASCII.GetString(byteReceive, 0, len);
                                fail_count = 0;
                                return true;
                            }
                            else
                            {
                                AutoDisConnect();
                                return false;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    /*if (ns != null)
                        ns.Close();*/
                    AutoDisConnect();
                    Console.WriteLine(ex.ToString());
                    return false;
                }

            }
            return false;
        }

        public bool GetBarCode(ref string[] barcodes)
        {
            bool result = true;
            string result_str = "";
            if(Read(ref result_str))
            {
                var results = new List<string>();
                MatchCollection msg_match = barcode_regex.Matches(result_str);
                foreach (Match m in msg_match)
                {
                    if (m.Success)
                    {
                        string barcode = m.Groups["barcode"].Value;
                        if (barcode == "ERR" || barcode == "NONE")
                            result = false;
                        else
                            results.Add(barcode);
                    }
                }
                barcodes = results.ToArray();
                if (msg_match.Count == 0)
                    result = false;
                return result;
            }
            return false;
        }
        /// <summary>
        /// 超时自动断连
        /// </summary>
        private void AutoDisConnect()
        {
            fail_count++;
            if (fail_count >= max_fail)
            {
                fail_count = 0;
                DisConnect();
            }
        }
        public new async Task<bool> ConnectAsync(string address, int times = 5)
        {
            if (client == null)
                client = new TcpClient();
            if (!IsConnect)
            {
                DisConnect();
                client = new TcpClient();
                client.ReceiveTimeout = 1000;
                client.SendTimeout = 1000;
                string[] addresses = address.Split(':');
                if (addresses.Length != 2)
                {
                    throw new FormatException("地址格式不正确");
                }
                else
                {
                    bool connected = await TcpAsyncConnect.ConnectAsync(
                        client,
                        addresses[0],
                        Convert.ToInt32(addresses[1]),
                        times);
                    if (IsConnect)
                    {
                        ns = client.GetStream();
                        ns.ReadTimeout = 1000;
                        ns.WriteTimeout = 1000;
                    }
                    return connected;
                }

            }
            return false;


        }
        public new async Task<bool> ConnectAsync(string ip, int port, int times = 5)
        {
            if (client == null)
                client = new TcpClient();
            if (!IsConnect)
            {
                DisConnect();
                client = new TcpClient();
                client.ReceiveTimeout = 1000;
                client.SendTimeout = 1000;
                bool connected = await TcpAsyncConnect.ConnectAsync(client, ip, port, times);

                if (IsConnect)
                {
                    ns = client.GetStream();
                    ns.ReadTimeout = 1000;
                    ns.WriteTimeout = 1000;
                }
                return connected;
            }
            return false;
        }
    }
}
